package com.town.garden.service.impl;

import cn.hutool.json.JSONUtil;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.town.garden.chain.AbstractServerStartHandler;
import com.town.garden.component.ProcessAlarmEventForRedisComponent;
import com.town.garden.constant.GlobalConstant;
import com.town.garden.entiy.request.SearchAlarmEventRequest;
import com.town.garden.entiy.request.SearchAlarmEventRequestData;
import com.town.garden.entiy.response.SearchAlarmEventResponse;
import com.town.garden.entiy.response.SearchAlarmEventResponseData;
import com.town.garden.enums.NVRApiEnum;
import com.town.garden.propertites.NvrProperties;
import com.town.garden.service.NvrAlarmEventService;
import com.town.garden.storage.NvrSessionStorage;
import com.town.garden.strategy.ProcessAlarmEventStrategy;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ScheduledExecutorService;

/**
 * @Description
 * @E-mail cwm3412638@163.com
 * @Author cwm
 * @Date 2022/5/13
 */
@Service(NvrAlarmEventServiceImpl.BEAN_NAME)
@Slf4j
public class NvrAlarmEventServiceImpl extends AbstractServerStartHandler implements NvrAlarmEventService, Runnable {
    public static final String BEAN_NAME = "nvrAlarmEventServiceImpl";
    /**
     * 下一个执行链对象
     * {@linkplain ProcessAlarmEventForRedisComponent}
     */
    @Autowired
    @Qualifier(ProcessAlarmEventForRedisComponent.BEAN_NAME)
    private AbstractServerStartHandler abstractServerStartHandler;
    @Autowired
    private NvrProperties nvrProperties;
    @Autowired
    private RestTemplate restTemplate;
    @Autowired
    private ScheduledExecutorService scheduledExecutorService;
    /**
     * 告警策略集合
     */
    @Autowired
    private List<ProcessAlarmEventStrategy> processAlarmEventStrategies;

    @Override
    public void handlerOperation() {
        //启动定时查询告警事件任务
        //scheduledExecutorService.scheduleAtFixedRate(this, 0, nvrProperties.getSearchAlarmEventTime(), TimeUnit.SECONDS);
        scheduledExecutorService.execute(this);
        //启动处理事件组件责任链
        abstractServerStartHandler.handlerOperation();
    }

    @Override
    public void run() {
        SearchAlarmEventRequest searchAlarmEventRequest = new SearchAlarmEventRequest();
        SearchAlarmEventRequestData searchAlarmEventRequestData = new SearchAlarmEventRequestData();
        searchAlarmEventRequestData.setSubscribeAiMetadata(true);
        searchAlarmEventRequestData.setNeedBackgroundImg(true);
        searchAlarmEventRequestData.setSubscribeIntelligence(true);
        if (Objects.nonNull(NvrSessionStorage.readerId) &&
                Objects.nonNull(NvrSessionStorage.lapNumber) &&
                Objects.nonNull(NvrSessionStorage.sequence)
        ) {
            searchAlarmEventRequestData.setReaderId(NvrSessionStorage.readerId);
            searchAlarmEventRequestData.setLapNumber(NvrSessionStorage.lapNumber);
            searchAlarmEventRequestData.setSequence(NvrSessionStorage.sequence);
        }
        searchAlarmEventRequest.setData(searchAlarmEventRequestData);
        try {
            ResponseEntity<SearchAlarmEventResponse> searchAlarmEventResponseResponseEntity = searchAlarmEvent(searchAlarmEventRequest);
            if (HttpStatus.OK.equals(searchAlarmEventResponseResponseEntity.getStatusCode())) {
                log.info("search alarm event response is :{}", JSONUtil.parse(searchAlarmEventResponseResponseEntity.getBody()));
                //设置下一次请求查询事件的链路信息
                SearchAlarmEventResponse searchAlarmEventResponse = searchAlarmEventResponseResponseEntity.getBody();
                assert searchAlarmEventResponse != null;
                SearchAlarmEventResponseData data = searchAlarmEventResponse.getData();
                NvrSessionStorage.lapNumber = data.getLapNumber();
                NvrSessionStorage.sequence = data.getSequence();
                NvrSessionStorage.readerId = data.getReaderId();
                for (ProcessAlarmEventStrategy processAlarmEventStrategy : processAlarmEventStrategies
                ) {
                    if (processAlarmEventStrategy.isMatch(data.getAlarmList())) {
                        processAlarmEventStrategy.doProcessAlarmEvent(data.getAlarmList());
                    }
                }
                //立马发送一下次请求
                scheduledExecutorService.execute(this);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public ResponseEntity<SearchAlarmEventResponse> searchAlarmEvent(SearchAlarmEventRequest searchAlarmEventRequest) throws JsonProcessingException {
        //拼接请求url
        final String url = GlobalConstant.HTTPS_PREFIX + nvrProperties.getNvrServerIp() + NVRApiEnum.EVENT_CHECK.getUrl();
        log.info("search alarm event parameter readerId is :{},sequence is :{},lapNumber is :{}", searchAlarmEventRequest.getData().getReaderId(), searchAlarmEventRequest.getData().getSequence(), searchAlarmEventRequest.getData().getLapNumber());
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        final HttpEntity<?> entity = new HttpEntity<>(objectMapper.writeValueAsString(searchAlarmEventRequest), NvrSessionStorage.headers);
        return restTemplate.exchange(url, HttpMethod.POST, entity, SearchAlarmEventResponse.class);
    }
}
